package com.ruoyi.mobile.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.UUIDgen;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.mobile.utils.*;
import com.ruoyi.mobile.utils.pay.HttpUtils;
import com.ruoyi.mobile.utils.pay.NonceUtil;
import com.ruoyi.mobile.utils.pay.SignUtil;
import com.ruoyi.system.api.resp.SysUserResp;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.constant.WechatPayHttpHeaders;
import com.wechat.pay.contrib.apache.httpclient.notification.Notification;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import com.ruoyi.common.security.utils.DictUtils;
import com.ruoyi.mobile.config.WxPayConfig;
import com.ruoyi.mobile.domain.*;
import com.ruoyi.mobile.mapper.*;
import com.ruoyi.system.api.domain.SysDictData;
import com.ruoyi.system.api.req.ShOrderReq;
import com.ruoyi.system.api.resp.ShOrderResp;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.mobile.service.IShOrderService;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 订单信息Service业务层处理
 * 
 * @author ruoyi
 * @date 2023-07-18
 */
@Service
@Transactional
public class ShOrderServiceImpl extends ServiceImpl<IShOrderMapper, ShOrderEntity> implements IShOrderService {
    @Autowired
    private ISysUserMapper sysUserMapper;
    @Autowired
    private IShProductMapper productMapper;
    @Autowired
    private ISysUserAddressMapper sysUserAddressMapper;
    @Autowired
    private IShMarketMapper shMarketMapper;
    @Autowired
    private IShProductPictureMapper productPictureMapper;
    @Autowired
    private MaterialOrderMapper orderInfoMapper;
    @Autowired
    private MaterialjkOrderMapper orderjkInfoMapper;
    @Autowired
    private MaterialInfoMapper infoMapper;
    @Autowired
    private MaterialInfojkMapper infojkMapper;
    @Autowired
    private RedisService redisService;
    private static CloseableHttpClient httpClient;
    private static CertificatesManager certificatesManager;
    private static Verifier verifier;

    @Override
    public NftResponse<Paginator<ShOrderResp>> getOrderList(ShOrderReq query) {
        if (query.getPageNo() == null || query.getPageNo() <= 0) {
            return new NftResponse<>(ResponseConstants.ERROR_CODE, "入参页码错误", null);
        }
        if (query.getPageSize() == null || query.getPageSize() <= 0) {
            return new NftResponse<>(ResponseConstants.ERROR_CODE, "入参每页数量错误", null);
        }
        List<SysDictData> dictLList = DictUtils.getDictCache("product_label");
        HashMap<String, String> dictLMap = new HashMap<>();
        for (SysDictData data:dictLList) {
            dictLMap.put(data.getDictValue(),data.getDictLabel());
        }
        Paginator<ShOrderResp> paginator = new Paginator<ShOrderResp>(query.getPageNo(), query.getPageSize(), 0, new ArrayList<>());
        QueryWrapper<ShOrderEntity> wrapperQuery = new QueryWrapper<>();
        if (null!=query.getCreateBy()) {
            wrapperQuery.eq(QueryUtil.camelToUnderline("createBy"), query.getCreateBy());
        }
        if (null!=query.getProductType()&&query.getProductType()==0) {
            wrapperQuery.inSql("product_id", "SELECT product_id FROM sh_product WHERE product_type<=80");
        }else if (null!=query.getProductType()&&query.getProductType()==-1) {
            wrapperQuery.inSql("product_id", "SELECT product_id FROM sh_product WHERE product_type>90");
        }else if (null!=query.getProductType()&&query.getProductType()==-2) {
            wrapperQuery.inSql("product_id", "SELECT product_id FROM sh_product WHERE product_type>80 and product_type<=90");
        }else {
            wrapperQuery.inSql("product_id", "SELECT product_id FROM sh_product WHERE product_type="+query.getProductType());
        }
        wrapperQuery.orderByDesc("create_time");
        IPage<ShOrderEntity> page = new Page<>(query.getPageNo(),query.getPageSize());
        IPage<ShOrderEntity> pageRtn = this.baseMapper.selectPage(page,wrapperQuery);
        List<ShOrderEntity> list = pageRtn.getRecords();
        List<ShOrderResp> result = BeanUtil.copyToList(list, ShOrderResp.class);
        for (ShOrderResp obj:result) {
            ShProductEntity product = productMapper.selectById(obj.getProductId());
            SysUserAddressEntity address = sysUserAddressMapper.selectById(obj.getAddressId());
            QueryWrapper<ShProductPictureEntity> wrapperQueryPic = new QueryWrapper<>();
            wrapperQueryPic.eq(QueryUtil.camelToUnderline("productId"), obj.getProductId());
            wrapperQueryPic.eq(QueryUtil.camelToUnderline("isVideo"), 0);
            List<ShProductPictureEntity> listPic = productPictureMapper.selectList(wrapperQueryPic);
            List<String> pics = new ArrayList<>();
            for (ShProductPictureEntity pic:listPic) {
                pics.add(pic.getProductPic());
            }
            obj.setProductPics(pics);
            obj.setProductName(product.getProductTitle());
            obj.setAddress(address.getAddress());
            obj.setShName(address.getName());
            obj.setShPhone(address.getPhone());
        }
        paginator.setPageNo(query.getPageNo());
        paginator.setPageSize(query.getPageSize());
        paginator.setTotalDataNum(pageRtn.getTotal());
        paginator.setPageData(result);
        return new NftResponse<>(ResponseConstants.SUCCESS_CODE, "获取成功", paginator);
    }

    @Override
    public NftResponse<Paginator<ShOrderResp>> getOrderPayList(ShOrderReq query) {
        if (query.getPageNo() == null || query.getPageNo() <= 0) {
            return new NftResponse<>(ResponseConstants.ERROR_CODE, "入参页码错误", null);
        }
        if (query.getPageSize() == null || query.getPageSize() <= 0) {
            return new NftResponse<>(ResponseConstants.ERROR_CODE, "入参每页数量错误", null);
        }
        List<ShOrderResp> pageResult = null;
        if (null!=query.getProductType()&&query.getProductType()==0) {
            pageResult = this.baseMapper.getOrderPayList1(query.getCreateBy(), query.getAppId());
        }else if (null!=query.getProductType()&&query.getProductType()==-1) {
            pageResult = this.baseMapper.getOrderPayList2(query.getCreateBy(), query.getAppId());
        }else if (null!=query.getProductType()&&query.getProductType()==-2) {
            pageResult = this.baseMapper.getOrderPayList3(query.getCreateBy(), query.getAppId());
        }else {
            pageResult = this.baseMapper.getOrderPayList(query.getCreateBy(), query.getProductType(), query.getAppId());
        }
        for (ShOrderResp resp:pageResult) {
            String productIds = resp.getProductIds();
            String[] productIdAry = productIds.split(",");
            List<String> pics = new ArrayList<>();
            StringBuffer productNames = new StringBuffer();
            for (String productId:productIdAry) {
                ShProductEntity product = productMapper.selectById(Long.valueOf(productId));
                QueryWrapper<ShProductPictureEntity> wrapperQueryPic = new QueryWrapper<>();
                wrapperQueryPic.eq(QueryUtil.camelToUnderline("productId"), Long.valueOf(productId));
                wrapperQueryPic.eq(QueryUtil.camelToUnderline("isVideo"), 0);
                List<ShProductPictureEntity> listPic = productPictureMapper.selectList(wrapperQueryPic);
                for (ShProductPictureEntity pic:listPic) {
                    pics.add(pic.getProductPic());
                }
                productNames = productNames.append(product.getProductTitle()).append(",");
            }
            SysUserAddressEntity address = sysUserAddressMapper.selectById(resp.getAddressId());
            if (null!=address) {
                resp.setAddress(address.getName() + "," + address.getPhone() + "," + address.getAddress());
            }
            resp.setProductName(productNames.toString());
            resp.setProductPics(pics);
            resp.setProductId(Long.valueOf(productIdAry[0]));
        }
        Paginator<ShOrderResp> paginator = new Paginator<ShOrderResp>(query.getPageNo(), query.getPageSize(), 0, new ArrayList<>());
        Integer start = (query.getPageNo()-1)*query.getPageSize();
        Integer end = query.getPageNo()*query.getPageSize();
        List<ShOrderResp> rtnList = pageResult.subList(start>pageResult.size()?pageResult.size():start,end>pageResult.size()?pageResult.size():end);
        paginator.setPageNo(query.getPageNo());
        paginator.setPageSize(query.getPageSize());
        paginator.setTotalDataNum(pageResult.size());
        paginator.setPageData(rtnList);
        return new NftResponse<>(ResponseConstants.SUCCESS_CODE, "获取成功", paginator);
    }

    @Override
    public NftResponse<JSONObject> insertOrderInfos(List<ShOrderReq> queryList) {
        for (ShOrderReq query:queryList) {
            if (null == query.getProductId() || query.getProductId() <= 0) {
                return new NftResponse<>(ResponseConstants.ERROR_CODE, "请输入下单商品", null);
            }
            if (null == query.getAmount() || query.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
                return new NftResponse<>(ResponseConstants.ERROR_CODE, "请输入订单金额", null);
            }
            if (null == query.getPayAmount() || query.getPayAmount().compareTo(BigDecimal.ZERO) <= 0) {
                return new NftResponse<>(ResponseConstants.ERROR_CODE, "请输入支付金额", null);
            }
        }
        String orderNo = UUIDgen.getUUID(20);
        List<ShOrderEntity> list = BeanUtil.copyToList(queryList, ShOrderEntity.class);
        BigDecimal fee = new BigDecimal(0);
        Long userId = queryList.get(0).getCreateBy();
        for (ShOrderEntity entity:list) {
            entity.setOrderNo(orderNo);
            entity.setCreateTime(DateUtils.getNowDate());
            fee = fee.add(entity.getPayAmount());
        }
        fee = fee.multiply(BigDecimal.valueOf(100));
        this.baseMapper.insertBatch(list);
        Long productIdId = queryList.get(0).getProductId();
        ShProductEntity product = productMapper.selectById(productIdId);
        if (product.getProductType()>80&&product.getProductType()<=90) {
            try {
                String appId = queryList.get(0).getAppId();
                NftResponse<JSONObject> rtn = this.wxPayFunction(appId, String.valueOf(fee.intValue()), orderNo, userId);
                return new NftResponse<>(ResponseConstants.SUCCESS_CODE, "下单成功", rtn.getData());
            }catch (Exception e){}
        }
        QueryWrapper<ShOrderEntity> wrapperQuery = new QueryWrapper<>();
        wrapperQuery.eq(QueryUtil.camelToUnderline("orderNo"), orderNo);
        List<ShOrderEntity> orderlist = this.baseMapper.selectList(wrapperQuery);
        for (ShOrderEntity entity:orderlist) {
            this.updateOrderInfo(entity.getId());
        }
        return new NftResponse<>(ResponseConstants.SUCCESS_CODE, "下单成功", null);
    }

    @Override
    public NftResponse<Boolean> updateOrderInfo(Long orderId) {
        if (null == orderId || orderId <= 0) {
            return new NftResponse<>(ResponseConstants.ERROR_CODE, "请输入订单主键信息", false);
        }
        ShOrderEntity entity = this.baseMapper.selectById(orderId);
        QueryWrapper<ShOrderEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(QueryUtil.camelToUnderline("id"), orderId);
        entity.setStatus(0);
        this.baseMapper.update(entity,wrapper);
        Long orderUserId = entity.getCreateBy();
        SysUserEntity sysUser = sysUserMapper.selectById(orderUserId);
        Long inviteId = sysUser.getInviteId();
        Long pinviteId = sysUser.getPinviteId();
        ShProductEntity product = productMapper.selectById(entity.getProductId());
        if (null!=product.getDiscount()&&product.getDiscount().compareTo(BigDecimal.ZERO)>0) {
            BigDecimal amount = product.getProductPrice().multiply(BigDecimal.valueOf(entity.getNum()));
            if (null!=product.getProductDiscount()&&product.getProductDiscount().doubleValue()>0) {
                amount = amount.multiply(product.getProductDiscount());
            }
            if (null!=inviteId&&inviteId>0) {
                ShMarketEntity market = new ShMarketEntity();
                market.setShopId(product.getShopId());
                market.setProductId(product.getId());
                market.setAmount(amount);
                market.setAccount(product.getDiscount());
                BigDecimal marketAmount = market.getAmount().multiply(market.getAccount());
                market.setMarketAmount(marketAmount);
                market.setCreateBy(inviteId);
                market.setCreateTime(DateUtils.getNowDate());
                shMarketMapper.insert(market);
            }
            if (null!=pinviteId&&pinviteId>0) {
                BigDecimal pdiscount = product.getDiscount();
                if (null!=product.getDiscountBl()&&product.getDiscountBl().doubleValue()>0) {
                    pdiscount = pdiscount.multiply(product.getDiscountBl());
                }
                ShMarketEntity market = new ShMarketEntity();
                market.setShopId(product.getShopId());
                market.setProductId(product.getId());
                market.setAmount(amount);
                market.setAccount(pdiscount);
                BigDecimal marketAmount = market.getAmount().multiply(market.getAccount());
                market.setMarketAmount(marketAmount);
                market.setCreateBy(pinviteId);
                market.setCreateTime(DateUtils.getNowDate());
                shMarketMapper.insert(market);
            }
        }
        return new NftResponse<>(ResponseConstants.SUCCESS_CODE, "修改成功", true);
    }

    public NftResponse<Boolean> updateOrderMInfo(Long orderId) {
        if (null == orderId || orderId <= 0) {
            return new NftResponse<>(ResponseConstants.ERROR_CODE, "请输入订单主键信息", false);
        }
        MaterialOrderEntity entity = this.orderInfoMapper.selectById(orderId);
        QueryWrapper<MaterialOrderEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(QueryUtil.camelToUnderline("id"), orderId);
        entity.setStatus(0);
        this.orderInfoMapper.update(entity,wrapper);
        Long orderUserId = entity.getUserId();
        SysUserEntity sysUser = sysUserMapper.selectById(orderUserId);
        Long inviteId = sysUser.getInviteId();
        Long pinviteId = sysUser.getPinviteId();
        MaterialInfoEntity product = this.infoMapper.selectById(entity.getMaterialId());
        if (null!=product.getDiscount()&&product.getDiscount().compareTo(BigDecimal.ZERO)>0) {
            SysUserEntity createUser = sysUserMapper.selectById(product.getUserId());
            BigDecimal amount = entity.getRealAmount();
            if (null!=product.getDiscount()&&product.getDiscount().doubleValue()>0) {
                amount = amount.multiply(product.getDiscount());
            }
            if (null!=inviteId&&inviteId>0) {
                ShMarketEntity market = new ShMarketEntity();
                market.setShopId(createUser.getDeptId());
                market.setProductId(product.getId());
                market.setAmount(amount);
                market.setAccount(product.getDiscount());
                BigDecimal marketAmount = market.getAmount().multiply(market.getAccount());
                market.setMarketAmount(marketAmount);
                market.setCreateBy(inviteId);
                market.setCreateTime(DateUtils.getNowDate());
                shMarketMapper.insert(market);
            }
            if (null!=pinviteId&&pinviteId>0) {
                BigDecimal pdiscount = product.getDiscount();
                if (null!=product.getDiscountBl()&&product.getDiscountBl().doubleValue()>0) {
                    pdiscount = pdiscount.multiply(product.getDiscountBl());
                }
                ShMarketEntity market = new ShMarketEntity();
                market.setShopId(createUser.getDeptId());
                market.setProductId(product.getId());
                market.setAmount(amount);
                market.setAccount(pdiscount);
                BigDecimal marketAmount = market.getAmount().multiply(market.getAccount());
                market.setMarketAmount(marketAmount);
                market.setCreateBy(pinviteId);
                market.setCreateTime(DateUtils.getNowDate());
                shMarketMapper.insert(market);
            }
        }
        return new NftResponse<>(ResponseConstants.SUCCESS_CODE, "修改成功", true);
    }

    public NftResponse<Boolean> updateOrderVInfo(Long orderId) {
        if (null == orderId || orderId <= 0) {
            return new NftResponse<>(ResponseConstants.ERROR_CODE, "请输入订单主键信息", false);
        }
        MaterialjkOrderEntity entity = this.orderjkInfoMapper.selectById(orderId);
        QueryWrapper<MaterialjkOrderEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(QueryUtil.camelToUnderline("id"), orderId);
        entity.setStatus(0);
        this.orderjkInfoMapper.update(entity,wrapper);
        Long orderUserId = entity.getUserId();
        SysUserEntity sysUser = sysUserMapper.selectById(orderUserId);
        Long inviteId = sysUser.getInviteId();
        Long pinviteId = sysUser.getPinviteId();
        MaterialInfojkEntity product = this.infojkMapper.selectById(entity.getMaterialId());
        if (null!=product.getDiscount()&&product.getDiscount().compareTo(BigDecimal.ZERO)>0) {
            SysUserEntity createUser = sysUserMapper.selectById(product.getUserId());
            BigDecimal amount = entity.getRealAmount();
            if (null!=product.getDiscount()&&product.getDiscount().doubleValue()>0) {
                amount = amount.multiply(product.getDiscount());
            }
            if (null!=inviteId&&inviteId>0) {
                ShMarketEntity market = new ShMarketEntity();
                market.setShopId(createUser.getDeptId());
                market.setProductId(product.getId());
                market.setAmount(amount);
                market.setAccount(product.getDiscount());
                BigDecimal marketAmount = market.getAmount().multiply(market.getAccount());
                market.setMarketAmount(marketAmount);
                market.setCreateBy(inviteId);
                market.setCreateTime(DateUtils.getNowDate());
                shMarketMapper.insert(market);
            }
            if (null!=pinviteId&&pinviteId>0) {
                BigDecimal pdiscount = product.getDiscount();
                if (null!=product.getDiscountBl()&&product.getDiscountBl().doubleValue()>0) {
                    pdiscount = pdiscount.multiply(product.getDiscountBl());
                }
                ShMarketEntity market = new ShMarketEntity();
                market.setShopId(createUser.getDeptId());
                market.setProductId(product.getId());
                market.setAmount(amount);
                market.setAccount(pdiscount);
                BigDecimal marketAmount = market.getAmount().multiply(market.getAccount());
                market.setMarketAmount(marketAmount);
                market.setCreateBy(pinviteId);
                market.setCreateTime(DateUtils.getNowDate());
                shMarketMapper.insert(market);
            }
        }
        return new NftResponse<>(ResponseConstants.SUCCESS_CODE, "修改成功", true);
    }

    @Override
    public NftResponse<Boolean> deleteOrderInfo(ShOrderReq query) {
        QueryWrapper<ShOrderEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(QueryUtil.camelToUnderline("order_no"), query.getOrderNo());
        this.baseMapper.delete(wrapper);
        return new NftResponse<>(ResponseConstants.SUCCESS_CODE, "删除成功", true);
    }

    @Override
    public NftResponse<JSONObject> wxPayFunction(String appId, String fee, String tradeNo, Long userId) throws Exception{
        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(WxPayConfig.privateKeyForDecrypt);
        // 获取证书管理器实例
        certificatesManager = CertificatesManager.getInstance();
        // 向证书管理器增加需要自动更新平台证书的商户信息
        certificatesManager.putMerchant(WxPayConfig.mchid, new WechatPay2Credentials(WxPayConfig.mchid,
                        new PrivateKeySigner(WxPayConfig.mchSerialNo, merchantPrivateKey)),
                WxPayConfig.apiV3Key.getBytes(StandardCharsets.UTF_8));
        // 从证书管理器中获取verifier
        verifier = certificatesManager.getVerifier(WxPayConfig.mchid);
        httpClient = WechatPayHttpClientBuilder.create()
                .withMerchant(WxPayConfig.mchid, WxPayConfig.mchSerialNo, merchantPrivateKey)
                .withValidator(new WechatPay2Validator(certificatesManager.getVerifier(WxPayConfig.mchid)))
                .build();
        SysUserEntity sysUser = sysUserMapper.selectById(userId);
        String openId = sysUser.getHopenId();
        //请求URL
        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
        // 请求body参数
        String reqdata = "{"
                + "\"amount\": {"
                + "\"total\": "+fee+","
                + "\"currency\": \"CNY\""
                + "},"
                + "\"mchid\": \""+WxPayConfig.mchid+"\","
                + "\"description\": \"订单费\","
                + "\"notify_url\": \""+WxPayConfig.notify_url+"\","
                + "\"payer\": {"
                + "\"openid\": \""+openId+"\"" + "},"
                + "\"out_trade_no\": \""+tradeNo+"\","
                + "\"appid\": \""+appId+"\"" + "}";
        StringEntity entity = new StringEntity(reqdata,"utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");
        //完成签名并执行请求
        CloseableHttpResponse response = httpClient.execute(httpPost);
        try {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) {
                System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
                String jsonStr = EntityUtils.toString(response.getEntity());
                JSONObject json = JSON.parseObject(jsonStr.replaceAll("\\\\",""));
                String prepay_id = json.getString("prepay_id");
                String nonceStr = NonceUtil.createNonce(32);
                long timestamp = Instant.now().getEpochSecond();
                String paySign = this.getPaySign(appId, timestamp, nonceStr, prepay_id);
                JSONObject jsonRtn = new JSONObject();
                jsonRtn.put("appId", appId);
                jsonRtn.put("nonceStr", nonceStr);
                jsonRtn.put("package", "prepay_id="+prepay_id);
                jsonRtn.put("signType", "RSA");
                jsonRtn.put("timeStamp", timestamp);
                jsonRtn.put("paySign", paySign);
                redisService.setCacheObject(userId+"pay", tradeNo, 30L, TimeUnit.MINUTES);
                return new NftResponse<>(ResponseConstants.SUCCESS_CODE, "支付成功", jsonRtn);
            } else if (statusCode == 204) {
                System.out.println("success");
            } else {
                System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
                throw new IOException("request failed");
            }
        } finally {
            response.close();
            httpClient.close();
        }
        return new NftResponse<>(ResponseConstants.SUCCESS_CODE, "支付成功", null);
    }

    @Override
    public NftResponse<String> wxpayNotify(HttpServletRequest request, HttpServletResponse response) {
        try {
            String readData = HttpUtils.readData(request);
            NotificationRequest notificationRequest = new NotificationRequest.Builder()
                    .withSerialNumber(request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_SERIAL))
                    .withNonce(request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_NONCE))
                    .withTimestamp(request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_TIMESTAMP))
                    .withSignature(request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_SIGNATURE))
                    .withBody(readData)
                    .build();
            NotificationHandler handler = new NotificationHandler(verifier, WxPayConfig.apiV3Key.getBytes(StandardCharsets.UTF_8));
            // 验签和解析请求体
            Notification notification = handler.parse(notificationRequest);
            AesUtil util = new AesUtil(WxPayConfig.apiV3Key.getBytes(StandardCharsets.UTF_8));
            Notification.Resource resource = notification.getResource();
            String ciphertext = resource.getCiphertext();
            String associatedData = resource.getAssociatedData();
            String nonce = resource.getNonce();
            String plainText = util.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8),nonce.getBytes(StandardCharsets.UTF_8),ciphertext);
            JSONObject json = JSON.parseObject(plainText.replaceAll("\\\\",""));
            if("SUCCESS".equals((String)json.get("trade_state"))){
                String out_trade_no = (String)json.get("out_trade_no");
                String openid = ((JSONObject)json.get("payer")).getString("openid");
                QueryWrapper<ShOrderEntity> wrapperQuery = new QueryWrapper<>();
                wrapperQuery.eq(QueryUtil.camelToUnderline("orderNo"), out_trade_no);
                List<ShOrderEntity> list = this.baseMapper.selectList(wrapperQuery);
                if (null!=list&&list.size()>0) {
                    for (ShOrderEntity entity:list) {
                        this.updateOrderInfo(entity.getId());
                        this.baseMapper.updateOrderStatusByOrderNo("1", out_trade_no);
                    }
                }else {
                    QueryWrapper<MaterialOrderEntity> wrapperQueryI = new QueryWrapper<>();
                    wrapperQuery.eq(QueryUtil.camelToUnderline("orderNo"), out_trade_no);
                    List<MaterialOrderEntity> listInfo = orderInfoMapper.selectList(wrapperQueryI);
                    if (null!=listInfo&&listInfo.size()>0) {
                        for (MaterialOrderEntity entity:listInfo) {
                            this.updateOrderMInfo(entity.getId());
                            this.baseMapper.updateOrderStatusByOrderNoM("1", out_trade_no);
                        }
                    }else {
                        QueryWrapper<MaterialjkOrderEntity> wrapperQueryJ = new QueryWrapper<>();
                        wrapperQuery.eq(QueryUtil.camelToUnderline("orderNo"), out_trade_no);
                        List<MaterialjkOrderEntity> listInfoJ = orderjkInfoMapper.selectList(wrapperQueryJ);
                        if (null!=listInfoJ&&listInfoJ.size()>0) {
                            for (MaterialjkOrderEntity entityJ:listInfoJ) {
                                this.updateOrderVInfo(entityJ.getId());
                                this.baseMapper.updateOrderStatusByOrderNoV("1", out_trade_no);
                            }
                        }
                    }
                }
                SysUserResp userResp = sysUserMapper.getUserByOpenId(openid);
                Long userId = userResp.getUserId();
                redisService.deleteObject(userId+"pay");
            }
            response.setStatus(200);
            return new NftResponse<>(ResponseConstants.SUCCESS_CODE, "回调成功", "SUCCESS");
        }catch (Exception e) {}
        return new NftResponse<>(ResponseConstants.SUCCESS_CODE, "回调成功", null);
    }

    private String getPaySign(String appid, long timestamp, String nonceStr, String prepay_id) {
        String source = appid + "\n";
        source += timestamp + "\n";
        source += nonceStr + "\n";
        source += "prepay_id=" + prepay_id + "\n";
        String paySign = "";
        try {
            paySign = SignUtil.signBySHA256WithRSA(source, WxPayConfig.privateKeyForDecrypt, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return paySign;
    }
}